public class PLLearnLayerFeature extends PLLearnLayer {
	PLFeature[][] mFeatures;
	protected PLMNDist mDists;
	int mRows =0;
	int mCols = 0;
	
	public PLLearnLayerFeature() {
		super();
	}
	
	public PLLearnLayerFeature(String name) {	
		super(name);
		Init();
	}
	
	public boolean Init() {
		// makes sense to test and add all available patterns
		String[] names = PLFeature.GetAllFeatureNames();

		// init the rows and the columns
		mRows = PLShape.GetNumShapes();		
		mCols = names.length;

		// init all the features
		mFeatures = new PLFeature[mRows][mCols];
		for (int j = 0; j < mCols; ++j) {
			for (int i =0; i < mRows; ++i) {
				mFeatures[i][j] = PLFeature.GetFeatureByName(names[j]);
			}						
		}

		// init distributions associated with the the features 
		mDists = new PLMNDist();		
		mDists.Init(mRows, mCols);

		return true;
	}

	public void Learn(PLShape query,PLShape response) {
		if (!query.IsValid() || !response.IsValid()) 
			return;
		
		// get the shape of the query and the equivalent distribution
		PLDist dist = mDists.GetDistributionAt(query.GetShapeId().getId());

		for (int j =0; j < NumFeatures(); ++j) {
			if (response.GetShapeId().getId() ==j) {
				// found the winner				
				dist.MultiplyValueAt(j, PLLearnUtils.GetWinnerMultiplicationFactor());
				// update attributes given the query respons
				mFeatures[query.GetShapeId().getId()][j].UpdateAttributes(query, response);
			} else {
				// loser				
				dist.MultiplyValueAt(j, PLLearnUtils.GetLoserMultiplicationFactor());
			}			
		}
	}

	public void Finished() {								
		SaveDataToFile();
	}

	public int NumFeatures() {return mCols;}

	// PRIVATE MEMBERS
	private boolean SaveDataToFile() {
		PLFileUtils.MakeFullDirPath(GetName());
		String filename = PLFileUtils.GetFeatureFile(GetName());

		PLRecordKeyValue<PLMNDist, PLFeature[][]> record = new PLRecordKeyValue<PLMNDist, PLFeature[][]>();

		record.Set(mDists, mFeatures);		
				
		// get the key value file name
		PLFileKeyValue<PLMNDist, PLFeature[][]> file = new PLFileKeyValue<PLMNDist, PLFeature[][]>(filename);
		file.WriteRecord(record);

		// just one record to write, we are all done
		file.FinishedWriting();
												
		// all done 	
		return true;
	}
}
